package mongorest

import (
	"encoding/json"
	"errors"
	"io"
	"strings"
	"time"

	"labix.org/v2/mgo"
)

type Record map[string]interface{}

func openCollection(database, collection string) (*mgo.Collection, error) {
	info := &mgo.DialInfo{
		Addrs:    strings.Split(settings.Mongodb.Addr, ","),
		Direct:   true,
		Timeout:  10 * time.Second, // TODO: move to settings
		Database: database,
	}
	if auth := settings.Mongodb.AuthForDatabase[database]; auth != nil {
		info.Username = auth.Username
		info.Password = auth.Password
	}
	session, err := mgo.DialWithInfo(info)
	if err != nil {
		return nil, err
	}
	session.SetSyncTimeout(time.Minute) // TODO: move to settings
	return session.DB("").C(collection), nil
}

type listDocsRequest struct {
	Database   string
	Collection string
}

func listDocuments(writer io.Writer, req *listDocsRequest) error {
	col, err := openCollection(req.Database, req.Collection)
	if err != nil {
		return err
	}

	var result []Record
	err = col.Find(nil).All(&result)
	if err != nil {
		return err
	}
	encoder := json.NewEncoder(writer)
	err = encoder.Encode(result)
	if err != nil {
		return err
	}
	return nil
}

type updateADocRequest struct {
	Database   string
	Collection string
	ID         string
	Record     Record
}

func updateADocument(writer io.Writer, req *updateADocRequest) error {
	col, err := openCollection(req.Database, req.Collection)
	if err != nil {
		return err
	}

	if req.ID == "" {
		return errors.New("_id not set")
	}
	return col.UpdateId(req.ID, req.Record)
}

type insertADocRequest struct {
	Database   string
	Collection string
	Record     Record
}

func insertADocument(writer io.Writer, req *insertADocRequest) error {
	col, err := openCollection(req.Database, req.Collection)
	if err != nil {
		return err
	}

	return col.Insert(req.Record)
}
